﻿using BLevy.Datos.Repositories;
using BLevy.Entidad;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Transactions;

namespace BLevy.Negocio
{
    public class Cobros
    {
        public static Cupon FindByCupon(string nro)
        {
            try
            {
                ICuponRepository _repository = new CuponRepository();
                return _repository.FindByNumero(nro);
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public static int RegistrarCobro(IList<string> cupones, DateTime fecha)
        {
            int resCobro = 0;
            int resCupon = 0;

            bool resultado = true;
            double total;
            Cupon _cupon;
            Socio _socio;

            ICobroRepository _cobroRepository = new CobroRepository();
            ICuponRepository _cuponRepository = new CuponRepository();
            ICobradorCuponRepository _cobradorCuponRepository = new CobradorCuponRepository();

            try
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    //IList<Socio> sociosL = _repositorySocio.FindAllActivos();
                    foreach (var cupon in cupones)
                    {
                        total = 0;

                        //obtengo el cupon

                        _cupon = Cupones.FindByNumero(cupon);

                        //obtengo el socio
                        _socio = Socios.FindById(_cupon.socio_id);

                        //obtengo el detalle, por cada detalle obtengo el periodo y calculo el total
                        IList<CuponDetalle> cuponDetalleL = Cupones.FindAllDetallesByIdCupon(_cupon.id);

                        foreach (CuponDetalle _cuponDetalle in cuponDetalleL)
                        {
                            if (_cuponDetalle.cupon.estado == "I")
                            {
                                if (_cuponDetalle.periodo.vencimiento_1 < fecha)
                                {
                                    total += (_cuponDetalle.importe + _cuponDetalle.periodo.recargo);
                                }
                                else
                                {
                                    total += _cuponDetalle.importe;
                                }
                            }
                        }

                        Cobro _cobro = new Cobro();
                        _cobro.cupon_id = _cupon.id;
                        _cobro.formapago_id = _socio.formapago_id;
                        _cobro.fecha = fecha;
                        _cobro.total = total;

                        //registro el cobro
                        resCobro = _cobroRepository.RegistrarCobro(_cobro);

                        if (resCobro > 0)
                        {
                            _cupon.estado = "P";
                            _cupon.transito = "I";

                            resCupon = _cuponRepository.Modify(_cupon);

                            //vinculo el cobro al ultimo cobrador que saco el cupon. Mientras el mismo este afuera de la empresa.
                            if (resCupon > 0)
                            {
                                //obtengo el afiliado 
                                //_cupon.socio = Socios.FindById(_cupon.socio_id);

                                //si el cupon esta afuera es por cobrador - 
                                if (_cupon.transito == "E")
                                {

                                    CobradorCupon _cobradorCupon = _cobradorCuponRepository.FindUltimaSalidaCupon(_cupon.id);
                                    //inserto en cobradorcobros
                                    CobradorCobro cobrador_cobro = new CobradorCobro();
                                    cobrador_cobro.cobrador_id = _cobradorCupon.cobrador_id;
                                    cobrador_cobro.cobro_id = resCobro;
                                    cobrador_cobro.cobradorcupon_id = _cobradorCupon.id;
                                    cobrador_cobro.fecha_cobro = _cobro.fecha;
                                    cobrador_cobro.cobrador = Cobradores.FindById(_cobradorCupon.cobrador_id);
                                    cobrador_cobro.comision = (total * (cobrador_cobro.cobrador.comision / 100));
                                    cobrador_cobro.estado = "I";

                                    //registro el registro del cobro asociado al cobrador
                                    int cobro_cobrador = _cobroRepository.RegistrarCobroCobrador(cobrador_cobro);
                                    if (cobro_cobrador == 0)
                                    {
                                        resultado = false;
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                resultado = false;
                                break;
                            }

                        }
                        else
                        {
                            resultado = false;
                            break;
                        }
                    }

                    if (resultado == true)
                    {
                        scope.Complete();
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }


            return resCobro;
        }

        public static int RegistrarCobroPorCobrador(IList<CobradorCupon> cuponesEntradaL, IList<Cobro> cuponesPagosL)
        {
            int resCupon = 0;
            int resCobro = 0;
            int resCuponCobro = 0;

            bool resultado = true;
            Cupon _cupon;
            
            ICobroRepository _cobroRepository = new CobroRepository();
            ICuponRepository _cuponRepository = new CuponRepository();
            ICobradorCuponRepository _cobradorCuponRepository = new CobradorCuponRepository();
            IDeudaRepository _deudaRepository = new DeudaRepository();

            try
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    //IList<Socio> sociosL = _repositorySocio.FindAllActivos();

                    foreach (CobradorCupon cuponEntrada in cuponesEntradaL)
                    {
                        CobradorCupon _cobradorCupon = new CobradorCupon();
                        _cobradorCupon.cobrador_id = cuponEntrada.cobrador_id;
                        _cobradorCupon.cupon_id = cuponEntrada.cupon_id;
                        _cobradorCupon.fecha = cuponEntrada.fecha;
                        _cobradorCupon.tipo_movimiento = "I";

                        resCupon = _cobradorCuponRepository.EntradaSalidaCupones(cuponEntrada);

                        _cobradorCupon.id = resCupon;

                        if (resCupon > 0)
                        {
                            Cobro cuponPago = cuponesPagosL.Where(c => c.cupon_id == _cobradorCupon.cupon_id).SingleOrDefault();
                            if (cuponPago != null)
                            {
                                Cobro _cobro = new Cobro();
                                _cobro.cupon_id = cuponPago.cupon_id;
                                _cobro.formapago_id = cuponPago.formapago_id;
                                _cobro.fecha = cuponPago.fecha;
                                _cobro.total = cuponPago.total;

                                //registro el cobro
                                resCobro = _cobroRepository.RegistrarCobro(_cobro);

                                _cobro.id = resCobro;

                                if (resCobro > 0)
                                {
                                    _cupon = Cupones.FindById(_cobro.cupon_id);
                                    _cupon.detalles = Cupones.FindAllDetallesPagoByIdCupon(_cupon.id);
                                    
                                    //cambio el estado al cupon
                                    _cupon.estado = "P";
                                    _cupon.transito = "I";

                                    resCuponCobro = _cuponRepository.PagoCupon(_cupon);

                                    if (resCuponCobro > 0)
                                    {
                                        //CobradorCupon _cobradorCupon = _cobradorCuponRepository.FindUltimaSalidaCupon(_cupon.id);
                                        //inserto en cobradorcobros
                                        CobradorCobro cobrador_cobro = new CobradorCobro();
                                        cobrador_cobro.cobrador_id = _cobradorCupon.cobrador_id;
                                        cobrador_cobro.cobro_id = resCobro;
                                        cobrador_cobro.cobradorcupon_id = _cobradorCupon.id;
                                        cobrador_cobro.fecha_cobro = _cobro.fecha;
                                        cobrador_cobro.cobrador = Cobradores.FindById(_cobradorCupon.cobrador_id);
                                        cobrador_cobro.comision = (_cobro.total * (cobrador_cobro.cobrador.comision / 100));
                                        cobrador_cobro.estado = "I";

                                        //registro el registro del cobro asociado al cobrador
                                        int cobro_cobrador = _cobroRepository.RegistrarCobroCobrador(cobrador_cobro);
                                        if (cobro_cobrador == 0)
                                        {
                                            resultado = false;
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        resultado = false;
                                        break;
                                    }

                                    // REGISTRAR DEUDA SI EXISTE
                                    if (_cupon.total != _cobro.total)
                                    {
                                        double saldo = (_cupon.total - _cobro.total);

                                        Deuda _deuda = new Deuda();
                                        _deuda.cobro_id = _cobro.id;
                                        _deuda.saldo = saldo;
                                        _deuda.fecha = _cobro.fecha;
                                        _deuda.estado = "I";

                                        int resDeuda = _deudaRepository.RegistrarDeuda(_deuda);

                                        if (resDeuda == 0)
                                        {
                                            resultado = false;
                                            break;
                                        }
                                    }

                                }
                                else
                                {
                                    resultado = false;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            resultado = false;
                            break;
                        }
                    }

                    if (resultado == true)
                    {
                        scope.Complete();
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return resCupon;
        }

        public static int RegistrarCobroPorDebito(string ruta_archivo, DateTime fecha)
        {
            int resultado = 0;
            Empresa empresa = Empresas.FindDatos("E");
            empresa.localidad = Localidades.FindById(empresa.localidad_id);

            IList<String> cupones_cobradosL = new List<String>();
            IList<DebitoRechazado> debitos_rechazados = new List<DebitoRechazado>();

            try
            {
                using (StreamReader reader = new StreamReader(ruta_archivo))
                {
                    string linea;
                    while ((linea = reader.ReadLine()) != null)
                    {
                        //obtengo la identificacion de empresa del archivo
                        string identificacion = linea.Substring(79, 1);
                        //lo comparo con la empresa
                        if (empresa.localidad.localidad.Substring(0, 1) == identificacion)
                        {
                            //tomo el numero de cupon del archivo
                            string numero_cupon = "0203" + linea.Substring(92, 8);
                            //tomo el codigo de autorizacion
                            string autorizado = linea.Substring(173, 3);
                            //le agrego el separador
                            numero_cupon = numero_cupon.Insert(4, "-");

                            //Obtengo los datos del cupon
                            Cupon cupon = new Cupon();
                            cupon = Cupones.FindByNumero(numero_cupon);

                            DebitoRechazado debito = new DebitoRechazado();

                            //pregunto si el codigo de autorizacion es aceptado "ACE" = aceptado, "R10" = falta de fondos
                            switch (autorizado)
                            {
                                case "ACE":
                                    cupones_cobradosL.Add(numero_cupon);
                                    break;
                                case "R02":                                                                        
                                    debito.cupon_id = cupon.id;
                                    debito.fecha = fecha;
                                    debito.error = "R02";
                                    debito.observacion = "CTA. CERRADA P/ORDEN JUDICIAL";

                                    debitos_rechazados.Add(debito);
                                    break;
                                case "R03":                                    
                                    debito.cupon_id = cupon.id;
                                    debito.fecha = fecha;
                                    debito.error = "R03";
                                    debito.observacion = "CUENTA INEXISTENTE";

                                    debitos_rechazados.Add(debito);
                                    break;
                                case "R08":
                                    debito.cupon_id = cupon.id;
                                    debito.fecha = fecha;
                                    debito.error = "R08";
                                    debito.observacion = "ORDEN DE NO PAGAR";

                                    debitos_rechazados.Add(debito);
                                    break;
                                case "R15":
                                    debito.cupon_id = cupon.id;
                                    debito.fecha = fecha;
                                    debito.error = "R15";
                                    debito.observacion = "BAJA DEL SERVICIO";

                                    debitos_rechazados.Add(debito);
                                    break;
                            }
                            
                        }
                    }

                    //si hay cupones a cobrar
                    if (cupones_cobradosL.Count > 0)
                    {
                        resultado = RegistrarCobro(cupones_cobradosL, fecha);
                    }

                    //verifico si hay debitos rechazados
                    if(debitos_rechazados.Count > 0)
                    {
                        int res = DebitosRechazados(debitos_rechazados);
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }

            return resultado;
        }

        public static Cobro FindById(int id)
        {
            try
            {
                ICobroRepository _repository = new CobroRepository();
                return _repository.FindById(id);
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public static int RegistrarCobroCobrador(CobradorCobro cobrador_cobro)
        {
            try
            {
                ICobroRepository _repository = new CobroRepository();
                return _repository.RegistrarCobroCobrador(cobrador_cobro);
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public static DateTime FechaPosibleCobro(int socio_id)
        {
            ICobroRepository _repository = new CobroRepository();
            DateTime fecha_posible;
            try
            {
                IList<Cobro> CobrosSocio = _repository.FindAllCobrosPorAfiliado(socio_id);

                int fechas = 0;
                int cantidad_cobros = CobrosSocio.Count;
                foreach (var i in CobrosSocio)
                {
                    int day = i.fecha.Day;
                    fechas += day;
                }

                Periodo periodo = Periodos.FindLast();

                if (cantidad_cobros != 0)
                {
                    int posible_dia = fechas / cantidad_cobros;

                    int month = DateTime.Now.Month;
                    int year = DateTime.Now.Year;

                    fecha_posible = new DateTime(year, month, posible_dia);

                    if (fecha_posible > periodo.vencimiento_2)
                    {
                        fecha_posible.AddMonths(1);
                    }
                }
                else
                {
                    fecha_posible = periodo.vencimiento_1;
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            return fecha_posible;
        }

        public static IList<Cobro> FindAll()
        {
            try
            {
                ICobroRepository _repository = new CobroRepository();
                return _repository.FindAll();
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public static IList<Cobro> FindAllFiltro(string numero_cupon, int? formapago_id, DateTime? desde, DateTime? hasta)
        {
            try
            {
                ICobroRepository _repository = new CobroRepository();
                return _repository.FindAllFiltro(numero_cupon, formapago_id, desde, hasta);
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public static Cobro FindByIdCupon(int cupon_id)
        {
            try
            {
                ICobroRepository _repository = new CobroRepository();
                return _repository.FindByIdCupon(cupon_id);
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public static int DebitosRechazados(IList<DebitoRechazado> debitos)
        {
            bool resultado = true;
            int resultado_debito = 0;
            try
            {
                using(TransactionScope scope = new TransactionScope())
                {
                    foreach(var row in debitos)
                    {
                        ICobroRepository _repository = new CobroRepository();
                        resultado_debito = _repository.DebitosRechazados(row);
                        if (resultado_debito == 0)
                        {
                            resultado = false;
                            break;
                        }
                    }
                    if(resultado != false)
                    {
                        scope.Complete();
                    }
                }
            }
            catch(Exception e)
            {
                throw e;
            }

            return resultado_debito;
        }


        public static IList<DebitoRechazado> FindAllDebitosRechazadosFiltro(string numerocupon, DateTime? desde, DateTime? hasta)
        {
            try
            {
                ICobroRepository _repository = new CobroRepository();
                return _repository.FindAllDebitosRechazadosFiltro(numerocupon, desde, hasta);
            }
            catch (Exception e)
            {
                throw e;
            }
        }


        public static IList<DebitoRechazado> FindDebitosRechazadosPorFecha(DateTime fecha)
        {
            try
            {
                ICobroRepository _repository = new CobroRepository();
                return _repository.FindDebitosRechazadosPorFecha(fecha);
            }
            catch (Exception e)
            {
                throw e;
            }
        }



    }
}
